package com.crm.business.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.ancun.netsign.model.AuthOutput;
import com.ancun.netsign.model.ContractOutput;
import com.ancun.netsign.model.SignUserOutput;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.crm.business.admin.service.AdminFileService;
import com.crm.business.admin.service.AdminMessageService;
import com.crm.business.admin.service.AdminService;
import com.crm.business.agreement.service.*;
import com.crm.business.crm.mapper.CrmAgreementMapper;
import com.crm.business.crm.service.*;
import com.crm.business.servlet.BaseServiceImpl;
import com.crm.business.utils.ActionRecordUtil;
import com.crm.business.utils.UserCacheUtil;
import com.crm.business.utils.UserUtil;
import com.crm.common.agreement.common.AgreementCodeEnum;
import com.crm.common.agreement.common.AiQianUtils;
import com.crm.common.agreement.entity.PO.*;
import com.crm.common.constant.Constants;
import com.crm.common.crm.common.CrmModel;
import com.crm.common.crm.constant.*;
import com.crm.common.crm.entity.BO.*;
import com.crm.common.crm.entity.PO.*;
import com.crm.common.crm.entity.VO.*;
import com.crm.common.exception.CustomException;
import com.crm.common.ka.core.common.Const;
import com.crm.common.ka.core.common.SystemCodeEnum;
import com.crm.common.ka.core.common.log.BehaviorEnum;
import com.crm.common.ka.core.entity.BasePage;
import com.crm.common.ka.core.feign.admin.entity.AdminMessage;
import com.crm.common.ka.core.feign.admin.entity.AdminMessageEnum;
import com.crm.common.ka.core.redis.RedisImpl;
import com.crm.common.ka.core.servlet.upload.FileEntity;
import com.crm.common.utils.DateUtils;
import com.crm.common.utils.StringUtils;
import com.crm.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CrmAgreementServiceImpl extends BaseServiceImpl<CrmAgreementMapper, CrmAgreement> implements ICrmAgreementService, CrmPageService {



    @Autowired
    private AdminService adminService;
    @Autowired
    private ICrmFieldService crmFieldService;

    @Autowired
    private ICrmAgreementDataService crmAgreementDataService;

    @Autowired
    private ICrmCustomerService crmCustomerService;

    @Autowired
    private ICrmStudentService crmStudentService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ActionRecordUtil actionRecordUtil;

    @Autowired
    private RedisImpl redis;

    @Autowired
    private AiQianUtils aiQianUtils;

    @Autowired
    private IBillAgreementTemplateService billAgreementTemplateService;

    @Autowired
    private IBillAgreementTemplateSignerService billAgreementTemplateSignerService;

    @Autowired
    private IBillAgreementTemplateParamsService billAgreementTemplateParamsService;

    @Autowired
    private IBillAgreementContractParamsService billAgreementContractParamsService;

    @Autowired
    private IBillAgreementContractSignerService billAgreementContractSignerService;

    @Autowired
    private IBillAgreementSealSubjectService billAgreementSealSubjectService;




    /**
     * 大的搜索框的搜索字段
     *
     * @return fields
     */
    @Override
    public String[] appendSearch() {
        return new String[]{ "customerName","telephone"};
    }

    @Override
    public CrmEnum getLabel() {
        return CrmEnum.AGREEMENT;
    }

    /**
     * 查询所有字段
     *
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryDefaultField() {
        List<CrmModelFiledVO> filedList = crmFieldService.queryField(getLabel().getType());
        return filedList;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryField(Integer id) {
        CrmModel crmModel = queryById(id);
        List<CrmModelFiledVO> list = crmFieldService.queryField(crmModel);
        return list;
    }

    @Override
    public Dict getSearchTransferMap() {
        return Dict.create()
                .set("customerId", "customerName");
    }

    /**
     * 分页查询
     *
     * @param search
     * @return
     */
    @Override
    public BasePage<Map<String, Object>> queryPageList(CrmSearchBO search) {
        search.setLabel(CrmEnum.AGREEMENT.getType());
        BasePage<Map<String, Object>> basePage = queryList(search);
        Long userId = UserUtil.getUserId();
        basePage.getList().forEach(map -> {

            //创建人名称回显
            if (ObjectUtil.isNotEmpty(map.get("createUserId"))) {
                Long createUserId = Long.valueOf(String.valueOf(map.get("createUserId")));
                if (ObjectUtil.isNotEmpty(createUserId)) {
                    String createUserName = UserCacheUtil.getUserName(createUserId);
                    map.put("createUserName", createUserName);
                }
            }

            //发起人所在部门
            if (ObjectUtil.isNotEmpty(map.get("createUserDeptId"))) {
                Long createUserDeptId = Long.valueOf(String.valueOf(map.get("createUserDeptId")));
                if (ObjectUtil.isNotEmpty(createUserDeptId)) {
                    String ownerDeptName = adminService.queryDeptName(Integer.valueOf(createUserDeptId.toString()));
                    map.put("createUserDeptName", ownerDeptName);
                }
            }

            // 负责人名称回显
            if (ObjectUtil.isNotEmpty(map.get("agreementOwnerUserId"))) {
                Long agreementOwnerUserId = Long.valueOf(String.valueOf(map.get("agreementOwnerUserId")));
                if (ObjectUtil.isNotEmpty(agreementOwnerUserId)) {
                    String ownerUserName = UserCacheUtil.getUserName(agreementOwnerUserId);
                    map.put("agreementOwnerUserName", ownerUserName);
                }
            }

            //负责人所在部门
            if (ObjectUtil.isNotEmpty(map.get("agreementOwnerDeptId"))) {
                Long agreementOwnerDeptId = Long.valueOf(String.valueOf(map.get("agreementOwnerDeptId")));
                if (ObjectUtil.isNotEmpty(agreementOwnerDeptId)) {
                    String ownerDeptName = adminService.queryAllDeptNameByDeptId(Integer.valueOf(agreementOwnerDeptId.toString()));
//                    String ownerDeptName = adminService.queryDeptName(Integer.valueOf(agreementOwnerDeptId.toString()));
                    map.put("agreementOwnerDeptName", ownerDeptName);
                }
            }

            //线索负责人名称回显
            if (ObjectUtil.isNotEmpty(map.get("agreementAssistantUserId"))) {
                Long agreementAssistantUserId = Long.valueOf(String.valueOf(map.get("agreementAssistantUserId")));
                if (ObjectUtil.isNotEmpty(agreementAssistantUserId)) {
                    String assistantUserName = UserCacheUtil.getUserName(agreementAssistantUserId);
                    map.put("agreementAssistantUserName", assistantUserName);
                }
            }


        });
        return basePage;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public CrmModel queryById(Integer id) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(Long.valueOf(id));
            crmAgreementDataService.setDataByBatchId(crmModel);
            // 权限类型  1不可编辑不可查看 2可查看不可编辑 3可编辑可查看
            //查询 分配给角色和机构  权限为  1  的字段 或 小于  1的字段
            List<String> stringList = SpringUtils.getBean(ICrmRoleFieldService.class).queryNoAuthField(crmModel.getLabel());
            List<String> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryNoAuthField(crmModel.getLabel());
            stringList = stringList.stream().filter(field -> deptFieldList.contains(field)).collect(Collectors.toList());

            stringList = stringList.stream().distinct().collect(Collectors.toList());

            stringList.forEach(crmModel::remove);
        } else {
            crmModel = new CrmModel(CrmEnum.AGREEMENT.getType());
        }
        return crmModel;
    }



    /**
     * 保存或新增信息
     *
     * @param saveBO, model
     */
    @Override
    public Map<String,String> addOrUpdate(CrmAgreementSaveBO saveBO, boolean isExcel) {

        Long userId = UserUtil.getUserId();
        String key = Constants.ADD_AGREEMENT + userId;
        String lockvalue = UUID.randomUUID().toString();
        boolean lock = redis.lock(key, lockvalue, 10, TimeUnit.SECONDS);
        if (!lock) {
            throw new CustomException(SystemCodeEnum.SYSTEM_BAD_REQUEST.getMsg(),SystemCodeEnum.SYSTEM_BAD_REQUEST.getCode());
        }
        try{

            Integer validateType = CrmBusinessEnum.SignTypeEnum.getTypeByRemark(saveBO.getSignType());
            if(!Optional.ofNullable(validateType).isPresent()){
                validateType = CrmBusinessEnum.SignTypeEnum.TYPE7.getType();
            }

            BillAgreementTemplate template = billAgreementTemplateService.getBaseMapper().selectById(saveBO.getTemplateId());
            if(!Optional.ofNullable(template).isPresent() || CrmBusinessEnum.PublicEnum.ZERO.getType().equals(template.getStatus())){
                throw new CustomException(AgreementCodeEnum.TEMPLATE_IS_UNDIFIND.getMsg(),AgreementCodeEnum.TEMPLATE_IS_UNDIFIND.getCode());
            }

            //模板签署方
            QueryWrapper<BillAgreementTemplateSigner> querySignerWrapper = new QueryWrapper<>();
            querySignerWrapper.eq("template_id",template.getTemplateId());
            List<BillAgreementTemplateSigner> templateSignerList = billAgreementTemplateSignerService.getBaseMapper().selectList(querySignerWrapper);

            //模板参数
            QueryWrapper<BillAgreementTemplateParams> queryParamsWrapper = new QueryWrapper<>();
            queryParamsWrapper.eq("template_id",template.getTemplateId());
            List<BillAgreementTemplateParams> templateParamsList = billAgreementTemplateParamsService.getBaseMapper().selectList(queryParamsWrapper);
            for(BillAgreementTemplateParams params : templateParamsList){
                String value = saveBO.getParams().get(params.getParamsKey());
                if(StringUtils.isEmpty(value)){
                    throw new CustomException(AgreementCodeEnum.TEMPLATE_PARAMS_CAN_NOT_NULL.getMsg(),AgreementCodeEnum.TEMPLATE_PARAMS_CAN_NOT_NULL.getCode());
                }
            }

            CrmAgreement crmAgreement = new CrmAgreement();
            if(CrmBusinessEnum.CustomerType.customer.getType().equals(saveBO.getCustomerType())){
                CrmCustomer customer = crmCustomerService.getById(saveBO.getCustomerId());
                if(!Optional.ofNullable(customer).isPresent() || StringUtils.isEmpty(customer.getTelephone())){
                    throw new CustomException(SystemCodeEnum.SYSTEM_NO_VALID.getMsg(),SystemCodeEnum.SYSTEM_NO_VALID.getCode());
                }
                crmAgreement.setTelephone(customer.getTelephone());
                crmAgreement.setCustomerName(customer.getCustomerName());
                if(Optional.ofNullable(customer.getOwnerUserId()).isPresent()){
                    crmAgreement.setAgreementOwnerUserId(customer.getOwnerUserId());
                }
                if(StringUtils.isNotEmpty(customer.getOwnerDeptId())){
                    crmAgreement.setAgreementOwnerDeptId(Long.valueOf(customer.getOwnerDeptId()));
                }
                if(StringUtils.isNotEmpty(customer.getAssistantUserId())){
                    crmAgreement.setAgreementAssistantUserId(Long.valueOf(customer.getAssistantUserId()));
                }

            }else if(CrmBusinessEnum.CustomerType.vip_customer.getType().equals(saveBO.getCustomerType())){
                CrmStudent student = crmStudentService.getById(saveBO.getCustomerId());
                if(!Optional.ofNullable(student).isPresent() || StringUtils.isEmpty(student.getTelephone())){
                    throw new CustomException(SystemCodeEnum.SYSTEM_NO_VALID.getMsg(),SystemCodeEnum.SYSTEM_NO_VALID.getCode());
                }
                crmAgreement.setTelephone(student.getTelephone());
                crmAgreement.setCustomerName(student.getCustomerName());
                if(Optional.ofNullable(student.getOwnerUserId()).isPresent()){
                    crmAgreement.setAgreementOwnerUserId(student.getOwnerUserId());
                }
                if(StringUtils.isNotEmpty(student.getOwnerDeptId())){
                    crmAgreement.setAgreementOwnerDeptId(Long.valueOf(student.getOwnerDeptId()));
                }
                if(Optional.ofNullable(student.getAssistantUserId()).isPresent()){
                    crmAgreement.setAgreementAssistantUserId(student.getAssistantUserId());
                }
            }
            crmAgreement.setSignType(saveBO.getSignType());
            crmAgreement.setIdCard(saveBO.getIdCard());

            try{
                //添加陌生用户
                aiQianUtils.addStranger(crmAgreement.getIdCard(),crmAgreement.getTelephone(),saveBO.getSignUserName());

                String contractNo = "xy"+IdUtil.simpleUUID();
                boolean b = aiQianUtils.createContract(contractNo,template.getTemplateNo(),saveBO.getParams());

                List<Long> subjectIdList = templateSignerList.stream().map(BillAgreementTemplateSigner::getSubjectId).collect(Collectors.toList());
                //签章主体
                QueryWrapper<BillAgreementSealSubject> querySubjectWrapper = new QueryWrapper<>();
                querySubjectWrapper.in("subject_id",subjectIdList);
                List<BillAgreementSealSubject> sealsubjectList = billAgreementSealSubjectService.getBaseMapper().selectList(querySubjectWrapper);
                Map<Long, BillAgreementSealSubject> subjectMap = sealsubjectList.stream().collect(Collectors.toMap(BillAgreementSealSubject::getSubjectId, option -> option, (oldOption, newOption) -> newOption));

                List<Map<String,String>> subjectList = new ArrayList<>();
                for(BillAgreementTemplateSigner signer : templateSignerList){
                    BillAgreementSealSubject subject = subjectMap.get(signer.getSubjectId());
                    Map<String,String> map = new HashMap<>();
                    map.put("key",signer.getSignerKey());
                    map.put("account",subject.getAccount());
                    map.put("sealNo",subject.getSealNo());
                    subjectList.add(map);
                }

                String signUrl = "";
                ContractOutput output = aiQianUtils.addSignerNoParams(contractNo,crmAgreement.getIdCard(),subjectList,validateType);
                List<SignUserOutput> signUserOutputList = output.getSignUser();
                for (SignUserOutput userOutput : signUserOutputList) {
                    if (userOutput.getAccount().equals(crmAgreement.getIdCard())) {
                        signUrl = userOutput.getSignUrl();
                    }
                }
                //更新数据
                SpringUtils.getBean(ICrmAgreementService.class).saveData(saveBO,isExcel,template,contractNo,signUrl,crmAgreement);
                Map<String,String> result = new HashMap<>();
                result.put("url",signUrl);
                return result;
            }catch (Exception e){
                throw e;
            }
        }finally {
            redis.unlock(key,lockvalue);
        }
    }

    @Override
    public boolean canSubmit(){
        return true;
    }

    /**
     * 保存数据
     * @param saveBO
     * @param isExcel
     * @param template
     * @param contractNo
     * @param signUrl
     * @param crmAgreement
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveData(CrmAgreementSaveBO saveBO, boolean isExcel,BillAgreementTemplate template,String contractNo,String signUrl,CrmAgreement crmAgreement){
        //模板签署方
        QueryWrapper<BillAgreementTemplateSigner> querySignerWrapper = new QueryWrapper<>();
        querySignerWrapper.eq("template_id",template.getTemplateId());
        List<BillAgreementTemplateSigner> templateSignerList = billAgreementTemplateSignerService.getBaseMapper().selectList(querySignerWrapper);

        //模板参数
        QueryWrapper<BillAgreementTemplateParams> queryParamsWrapper = new QueryWrapper<>();
        queryParamsWrapper.eq("template_id",template.getTemplateId());
        List<BillAgreementTemplateParams> templateParamsList = billAgreementTemplateParamsService.getBaseMapper().selectList(queryParamsWrapper);

        String batchId = IdUtil.simpleUUID();
        Date now = new Date();
        crmAgreement.setSignUserName(saveBO.getSignUserName());
        crmAgreement.setCustomerId(saveBO.getCustomerId());
        crmAgreement.setCustomerType(saveBO.getCustomerType());
        crmAgreement.setTemplateId(saveBO.getTemplateId());
        crmAgreement.setTemplateName(saveBO.getTemplateName());
        crmAgreement.setCreateTime(now);
        crmAgreement.setCreateUserId(UserUtil.getUserId());
        crmAgreement.setCreateUserDeptId(Long.valueOf(UserUtil.getUser().getDeptId()));
        crmAgreement.setBatchId(batchId);
        crmAgreement.setContractNo(contractNo);
        crmAgreement.setSignUrl(signUrl);
        crmAgreement.setSignStatus(CrmBusinessEnum.SignStatusEnum.NO_SIGN.getRemarks());
        save(crmAgreement);


        List<BillAgreementContractParams> contractParams = new ArrayList<>();
        for(BillAgreementTemplateParams templateParams : templateParamsList){
            BillAgreementContractParams params = new BillAgreementContractParams();
            BeanUtil.copyProperties(templateParams,params);
            params.setParamsId(null);
            params.setCreateTime(now);
            params.setUpdateTime(now);
            params.setAgreementId(crmAgreement.getAgreementId());
            params.setParamsValue(saveBO.getParams().get(templateParams.getParamsKey()));
            contractParams.add(params);
        }
        billAgreementContractParamsService.addList(contractParams);


        List<BillAgreementContractSigner> contractSigners = new ArrayList<>();
        for(BillAgreementTemplateSigner templateSigner : templateSignerList){
            BillAgreementContractSigner signer = new BillAgreementContractSigner();
            BeanUtil.copyProperties(templateSigner,signer);
            signer.setSignerId(null);
            signer.setCreateTime(now);
            signer.setUpdateTime(now);
            signer.setAgreementId(crmAgreement.getAgreementId());
            contractSigners.add(signer);
        }
        billAgreementContractSignerService.addList(contractSigners);

        CrmModelSaveBO modelSaveBO = new CrmModelSaveBO();
        modelSaveBO.setEntity(BeanUtil.beanToMap(crmAgreement));
        savePage(modelSaveBO, crmAgreement.getAgreementId(), isExcel);
    }

    @Override
    public void setOtherField(Map<String, Object> map) {
        String ownerUserName = UserCacheUtil.getUserName((Long) map.get("agreementOwnerUserId"));
        map.put("ownerUserName", ownerUserName);
        String createUserName = UserCacheUtil.getUserName((Long) map.get("createUserId"));
        map.put("createUserName", createUserName);
        String teacherName = UserCacheUtil.getUserName((Long) map.get("agreementAssistantUserId"));
        map.put("assistantUserName", teacherName);
    }



    /**
     * 导出
     *
     * @param response resp
     * @param search   搜索对象
     */
    @Override
    public void exportExcel(HttpServletResponse response, CrmSearchBO search) {
        List<Map<String, Object>> dataList = queryPageList(search).getList();
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = crmFieldService.queryListHead(getLabel().getType());
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "协议签署信息");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
//            dataList.forEach(record -> {
//                record.put("customerType", Objects.equals(1, record.get("customerType")) ? "vip学员" : "学员");
//            });
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 30);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            String fileName = "协议" + DateUtils.dateTimeNow() + ".xls";
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);

            // 新增消息
            addMessage(dataList.size() <= 0 ? "0" : String.valueOf(dataList.size()), "导出数据" + String.valueOf(dataList.size()) + "条", UserUtil.getUserId(), AdminMessageEnum.CRM_AGREEMENT_EXPORT.getType(), null);

        } catch (Exception e) {
            log.error("导出线索错误：", e);
        }
    }


    @Override
    public List<CrmModelFiledVO> information(Integer agreementId) {
        //将主表和子表数据查询为一个map
        //字段类型 1不可编辑不可查看 2可查看不可编辑 3可编辑可查看
        //将map 中 字段类型 小于等于1 的key  remove掉
        CrmModel crmModel = queryById(agreementId);
        Set<String> set = crmModel.keySet();
        List<String> keyList = new ArrayList<>(set);

        List<String> systemFieldList = Arrays.asList("createUserName", "createTime", "updateTime");
        List<CrmModelFiledVO> crmModelFiledVOS = queryInformation(crmModel, keyList);
        List<CrmModelFiledVO> filedVOS = crmModelFiledVOS.stream().sorted(Comparator.comparingInt(r -> -r.getFieldType())).peek(r -> {
            if (FieldEnum.SELECT.getType().equals(r.getType())) {
                if (CollUtil.isEmpty(r.getSetting())) {
                    r.setSetting(new ArrayList<>(StrUtil.splitTrim(r.getOptions(), Const.SEPARATOR)));
                }
            }
            if (systemFieldList.contains(r.getFieldName())) {
                r.setAuthLevel(2);
                r.setSysInformation(1);
            } else {
                r.setSysInformation(0);
            }
        }).collect(Collectors.toList());

        List<String> removeField = Arrays.asList("");
        filedVOS.removeIf(item -> removeField.contains(item.getFieldName()));

        return filedVOS;
    }

    /**
     * 查询文件数量
     *
     * @param agreementId id
     * @return data
     */
    @Override
    public CrmInfoNumVO num(Integer agreementId) {
        List<String> batchIdList = new ArrayList<>();
        CrmAgreement crmAgreement = getById(agreementId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmAgreementData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmAgreementData::getValue);
            wrapper.eq(CrmAgreementData::getBatchId, crmAgreement.getBatchId());
            wrapper.in(CrmAgreementData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            batchIdList.addAll(crmAgreementDataService.listObjs(wrapper, Object::toString));
        }
        batchIdList.add(crmAgreement.getBatchId());
        CrmInfoNumVO numVO = new CrmInfoNumVO();
        numVO.setFileCount(fileService.queryNum(batchIdList));
        return numVO;
    }


    /**
     * 查询文件列表
     *
     * @param agreementId id
     * @return file
     */
    @Override
    public List<FileEntity> queryFileList(Integer agreementId) {
        List<FileEntity> fileEntityList = new ArrayList<>();
        CrmAgreement crmAgreement = getById(agreementId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        fileService.queryFileList(crmAgreement.getBatchId()).forEach(fileEntity -> {
            fileEntity.setSource("附件上传");
            fileEntity.setReadOnly(0);
            fileEntityList.add(fileEntity);
        });
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmAgreementData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmAgreementData::getValue);
            wrapper.eq(CrmAgreementData::getBatchId, crmAgreement.getBatchId());
            wrapper.in(CrmAgreementData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            List<FileEntity> data = fileService.queryFileList(crmAgreementDataService.listObjs(wrapper, Object::toString));
            data.forEach(fileEntity -> {
                fileEntity.setSource("协议详情");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        return fileEntityList;
    }

    @Override
    public void updateInformation(CrmUpdateInformationBO updateInformationBO) {
        String batchId = updateInformationBO.getBatchId();
        Integer agreementId = updateInformationBO.getId();
        updateInformationBO.getList().forEach(record -> {
            CrmAgreement oldAgree = getById(updateInformationBO.getId());
            Map<String, Object> oldAgreementMap = BeanUtil.beanToMap(oldAgree);
            if (record.getInteger("fieldType") == 1) {
                Map<String, Object> crmAgreementMap = new HashMap<>(oldAgreementMap);
                crmAgreementMap.put(record.getString("fieldName"), record.get("value"));
                CrmAgreement crmAgreement = BeanUtil.mapToBean(crmAgreementMap, CrmAgreement.class, true);
//                actionRecordUtil.updateRecord(oldAgreementMap, crmAgreementMap, CrmEnum.AGREEMENT,  crmAgreement.getTemplateName(), crmAgreement.getAgreementId());
                update().set(StrUtil.toUnderlineCase(record.getString("fieldName")), record.get("value")).eq("agreement_id", updateInformationBO.getId()).update();
            } else if (record.getInteger("fieldType") == 0 || record.getInteger("fieldType") == 2) {

                CrmAgreementData agreementData = crmAgreementDataService.lambdaQuery().select(CrmAgreementData::getValue)
                        .eq(CrmAgreementData::getFieldId, record.getInteger("fieldId"))
                        .eq(CrmAgreementData::getBatchId, batchId).one();
                String value = agreementData != null ? agreementData.getValue() : null;
                boolean isUpdate = false;
                if ((null == value && null == record.get("value"))) {
                    isUpdate = false;
                } else if (null != value && !value.equals(String.valueOf(record.get("value")))) {
                    isUpdate = true;
                } else if (null != record.get("value") && !String.valueOf(record.get("value")).equals(value)) {
                    isUpdate = true;
                }
                if (isUpdate) {
                    String detail = actionRecordUtil.getDetailByFormTypeAndValue(record, value);
                    actionRecordUtil.publicContentRecord(CrmEnum.AGREEMENT, BehaviorEnum.UPDATE, agreementId, oldAgree.getTemplateName(), detail);
                    boolean bol = crmAgreementDataService.lambdaUpdate()
                            .set(CrmAgreementData::getName, record.getString("fieldName"))
                            .set(CrmAgreementData::getValue, record.getString("value"))
                            .eq(CrmAgreementData::getFieldId, record.getInteger("fieldId"))
                            .eq(CrmAgreementData::getBatchId, batchId).update();
                    if (!bol) {
                        CrmAgreementData crmAgreementData = new CrmAgreementData();
                        crmAgreementData.setFieldId(record.getInteger("fieldId"));
                        crmAgreementData.setName(record.getString("fieldName"));
                        crmAgreementData.setValue(record.getString("value"));
                        crmAgreementData.setCreateTime(new Date());
                        crmAgreementData.setBatchId(batchId);
                        crmAgreementDataService.save(crmAgreementData);
                    }
                }
            }
            updateField(record, agreementId);
        });

    }

    @Override
    public String signAgreementCallBack(String contractNo,String signTime){
        //加锁
        String key = Constants.CONTRACT_SING_CALL_BACK + contractNo;
        String value = UUID.randomUUID().toString();
        boolean b = redis.lock(key, value, 10, TimeUnit.SECONDS);
        if (!b) {
            return StringUtils.EMPTY;
        }

        try {
            QueryWrapper<CrmAgreement> queryAgreementWrapper = new QueryWrapper<>();
            queryAgreementWrapper.eq("contract_no",contractNo);
            CrmAgreement crmAgreement = getBaseMapper().selectOne(queryAgreementWrapper);

            if (!Optional.ofNullable(crmAgreement).isPresent()) {
                return StringUtils.EMPTY;
            }
            if (CrmBusinessEnum.SignStatusEnum.SIGN_SUCCESS.getRemarks().equals(crmAgreement.getSignStatus())) {
                return "ok";
            }
            Object object = aiQianUtils.queryContractStatus(contractNo);
            if (Optional.ofNullable(object).isPresent()) {
                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(object));
                if (!Integer.valueOf(2).equals(jsonObject.getInteger("status"))) {
                    return StringUtils.EMPTY;
                }
            } else {
                return StringUtils.EMPTY;
            }
            CrmAgreement upAgreement = new CrmAgreement();
            upAgreement.setAgreementId(crmAgreement.getAgreementId());
            upAgreement.setSignTime(new Date());
            upAgreement.setSignStatus(CrmBusinessEnum.SignStatusEnum.SIGN_SUCCESS.getRemarks());
            getBaseMapper().updateById(upAgreement);
            //修改es
            Integer id = Integer.valueOf(String.valueOf(upAgreement.getAgreementId()));
            Map<String, Object> map = new HashMap<>();
            map.put("signStatus", CrmBusinessEnum.SignStatusEnum.SIGN_SUCCESS.getRemarks());
            map.put("signTime", DateUtil.formatDateTime(new Date()));
            updateField(map, Collections.singletonList(id));


            AdminMessage adminMessage = new AdminMessage();
            adminMessage.setCreateTime(new Date());
            adminMessage.setCreateUser(0l);
            adminMessage.setLabel(6);
            adminMessage.setContent("学员已完成电子协议的签署");
            adminMessage.setTitle(crmAgreement.getCustomerName());
            adminMessage.setRecipientUser(crmAgreement.getCreateUserId());
            adminMessage.setTypeId(Integer.valueOf(String.valueOf(crmAgreement.getCustomerId())));
            adminMessage.setSubmitUserId(crmAgreement.getCreateUserId());
            if(CrmBusinessEnum.CustomerType.customer.getType().equals(crmAgreement.getCustomerType())){
                adminMessage.setType(AdminMessageEnum.CUSTOMER_AGREEMENT_SIGN_NOTICE.getType());
            }else if(CrmBusinessEnum.CustomerType.vip_customer.getType().equals(crmAgreement.getCustomerType())){
                adminMessage.setType(AdminMessageEnum.STUDENT_AGREEMENT_SIGN_NOTICE.getType());
            }
            SpringUtils.getBean(AdminMessageService.class).save(adminMessage);

            return "ok";
        } finally {
            redis.unlock(key, value);
        }
    }


    /**
     * 获取合同信息
     *
     * @param contractNo
     * @return
     */
    @Override
    public Map<String, Object> checkContract(String contractNo) {

        Object o = aiQianUtils.getContract(contractNo);
        ContractOutput contractOutput = JSONObject.parseObject(JSONObject.toJSONString(o), ContractOutput.class);
        Map<String, Object> result = new HashMap<>();
        List<SignUserOutput> signUserOutputList = contractOutput.getSignUser();
        if (CollectionUtil.isNotEmpty(signUserOutputList)) {
            SignUserOutput userOutput = signUserOutputList.stream().findFirst().get();
            result.put("url", userOutput.getSignUrl());
        }
//        for(SignUserOutput userOutput : signUserOutputList){
//            if(userOutput.getAccount().startsWith("account")){
//                result.put("url",userOutput.getSignUrl());
//                break;
//            }
//        }
        return result;
    }

    @Override
    public Map<String,Object> contractNum(Long cusotmerId,String customerType){

        CrmAgreement query = new CrmAgreement();
        query.setCustomerId(cusotmerId);
        query.setCustomerType(customerType);
        Integer num = getBaseMapper().num(query);
        Map<String,Object> result = new HashMap<>();
        result.put("num",num);
        return result;
    }

    @Override
    public Map<String,Object> contractStatis(){
//        BillGroup group = billGroupService.queryBillGroup(OrgIdThreadLocal.getOrgId());
        CrmAgreement query = new CrmAgreement();
        Integer num = getBaseMapper().num(query);
        query.setSignStatus(CrmBusinessEnum.SignStatusEnum.SIGN_SUCCESS.getRemarks());
        Integer sign = getBaseMapper().num(query);
        Map<String,Object> result = new HashMap<>();
        result.put("all",0);
        result.put("used",num);
        result.put("sign",sign);
        result.put("residue",0);
        return result;
    }


    @Override
    public void upAgreementNumCache(Integer upNum,Integer type){

        boolean b = redis.hashMapKey(Constants.GROUP_AGREEMENT,"0");
        if(!b){
            redis.put(Constants.GROUP_AGREEMENT,"0",0);
        }
        Integer all = redis.get(Constants.GROUP_AGREEMENT,"0");
        if(CrmBusinessEnum.PublicEnum.ONE.getType().equals(type)){
            if(all.compareTo(upNum) < 0){
                throw new CustomException("数量错误，请稍后再更新！");
            }
            upNum = 0 - upNum;
        }
        redis.decrByCacheCountMap(redis.LUA_SCRIPT_DECRBY_UNTIL,Constants.GROUP_AGREEMENT,"0",upNum);
    }

    @Override
    public BasePage<Map<String, Object>> queryAgreement(CrmAgreementPageBo pageEntity){
        if(!Optional.ofNullable(pageEntity.getCustomerId()).isPresent() || !Optional.ofNullable(pageEntity.getCustomerId()).isPresent()){
            throw new CustomException(SystemCodeEnum.SYSTEM_NO_VALID.getMsg(),SystemCodeEnum.SYSTEM_NO_VALID.getCode());
        }

        //其余角色根据数据权限查询
        List<Long> userIdList = SpringUtils.getBean(AdminService.class).queryUserIdsByRoleIds();
        //管理部门 数据权限
        List<Long> ManageDeptUserIdList = SpringUtils.getBean(AdminService.class).queryUserIdsByManageDept();
        userIdList.addAll(ManageDeptUserIdList);
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());

        BasePage<Map<String, Object>> basePage = pageEntity.parse();
        BasePage<Map<String, Object>> page = getBaseMapper().queryAgreement(basePage,pageEntity.getCustomerId(),pageEntity.getCustomerType(),userIdList);
        page.getList().forEach(map -> {
            //创建人名称回显
            if (ObjectUtil.isNotEmpty(map.get("createUserId"))) {
                Long createUserId = Long.valueOf(String.valueOf(map.get("createUserId")));
                if (ObjectUtil.isNotEmpty(createUserId)) {
                    String createUserName = UserCacheUtil.getUserName(createUserId);
                    map.put("createUserName", createUserName);
                }
            }
        });
        return page;
    }

    /**
     * 三要素认证
     * @param signUserName
     * @param idCard
     * @param telephone
     * @return
     */
    @Override
    public Map<String,Object> personAuth(String signUserName,String idCard,String telephone){

        Map<String,Object> result = new HashMap<>(3);
        AuthOutput authOutput =  aiQianUtils.personVerifyMobile3(signUserName,idCard,telephone);
        result.put("result",authOutput.getResult());
        result.put("serialNo",authOutput.getSerialNo());
        return result;
    }
}
